const Koa = require('koa');
const path = require('path');
const fs = require('fs');
const utils = require('../util')
const io = require('socket.io-client');
const service = require('../service/methods')
const Sql = require('./Sql')
const {chainablize} = require('./../util')
chainablize(Sql)
module.exports = class LCBot {
    constructor({apiRoot, ServerQQ}) {
        this.app = new Koa();
        this.utils = utils;
        this.ServerQQ = ServerQQ;
        this.callbacks = {message: [], event: [], post: [], get: []};
        this.socket = io(apiRoot, {
            transports: ['websocket']
        });
        Object.keys({...service}).forEach(funcName => {
            this[funcName] = service[funcName]
        })
        this.sql = new Sql();
        let _self = this;
        this.sql.select(['*'])
            .from('user')
            .where([{uName: {value: 'bocai', _like: true}}])
            .orderBy({uName: 'ASC',_type:'field'})
            .groupBy(['uName'])
            .having([{
                uName: {
                    value: _self.sql.select(['uName'])
                        .from('user')
                        .where([{uName: {value: 'cai', _like: true}}])
                        .link(),
                    _in: true
                }
            }])
            .exec()
            .then(res => {
                console.log('result', res)
            }).catch(err => {
            console.error('promise Err', err)
        })
        // this.sql.update('user')
        //     .set({upass:'123457'})
        //     .where({user:[{userId:{value:'user1'}}]})
        //     .exec()
        //     .then(res=>console.log(res))
        //     .catch(err=>console.error(err))
        this.socket.on('connect', function () {
            _self.socket.emit('GetWebConn', _self.ServerQQ + '', (data) => {
                console.log(`webSocket已连接至服务器: ${apiRoot} ${data}`)
            });
        });
        //统一事件管理如好友进群事件 好友请求事件 退群等事件集合
        this.socket.on('OnEvents', function (data) {
            if (data.CurrentQQ == _self.ServerQQ) {
                const callbacks = _self.callbacks['event'];
                if (callbacks) {
                    for (const cb of callbacks) {
                        cb(data.CurrentPacket.Data);
                    }
                }
            }
        });
        //收到好友消息的回调事件
        _self.socket.on('OnFriendMsgs', function (data) {
            if (data.CurrentQQ == _self.ServerQQ) {
                let context = {
                    content: data.CurrentPacket.Data.Content,
                    from: data.CurrentPacket.Data.FromUin,
                    to: data.CurrentPacket.Data.ToUin,
                    msgId: data.CurrentPacket.Data.MsgSeq,
                    msgType: data.CurrentPacket.Data.MsgType,
                    type: 1,
                    RedBaginfo: data.CurrentPacket.Data.RedBaginfo
                }
                _self.SenseFilter(context.content).then(res => {
                    if (res.errcode !== 87014 && context.from != _self.ServerQQ) {
                        const callbacks = _self.callbacks['message'];
                        if (callbacks) {
                            for (const cb of callbacks) {
                                cb(context);
                            }
                        }
                    }
                })
            }
        });
        //收到群消息的回调事件
        _self.socket.on('OnGroupMsgs', function (data) {
            if (data.CurrentQQ == _self.ServerQQ) {
                let context = {
                    content: data.CurrentPacket.Data.Content,
                    fromGroup: data.CurrentPacket.Data.FromGroupId,
                    groupName: data.CurrentPacket.Data.FromGroupName,
                    memberId: data.CurrentPacket.Data.FromUserId,
                    memberNickName: data.CurrentPacket.Data.FromNickName,
                    msgId: data.CurrentPacket.Data.MsgSeq,
                    msgTime: data.CurrentPacket.Data.MsgTime,
                    msgRandom: data.CurrentPacket.Data.MsgRandom,
                    msgType: data.CurrentPacket.Data.MsgType,
                    type: 2,
                    RedBaginfo: data.CurrentPacket.Data.RedBaginfo
                }
                const callbacks = _self.callbacks['message'];
                if (callbacks) {
                    for (const cb of callbacks) {
                        cb(context);
                    }
                }
            }
        });
        this.loadCurrentQQAllInfo();
        this.getAppToken()
    }

    on(event_type, callback) {
        this.callbacks[event_type].push(callback);
        return callback;
    }

    off(event_type, callback) {
        let idx = this.callbacks[event_type].indexOf(callback);
        while (idx > -1) {
            this.callbacks[event_type].splice(idx, 1);
            idx = this.callbacks[event_type].indexOf(callback);
        }
    }

    use(func) {
        this.app.use(func)
    }

    listen(...args) {
        this.app.listen(...args);
    }

    loadCurrentQQAllInfo() {
        let _this = this;
        let runtimeValue = require('../jsonDb/runtimeValues.json'), promiseArr = [];
        promiseArr.push(
            this.getFriendList({}).then(data => {
                let friendObj = {};
                data.Friendlist.forEach(friend => {
                    friendObj[friend.FriendUin] = friend
                })
                runtimeValue = {
                    ...runtimeValue,
                    friends: friendObj,
                    friendNums: data.Friendlist.length
                }
            }),
            this.getGroupList({}).then(data => {
                return new Promise(resolve => {
                    let groupObj = {}
                    let tempProList = [];
                    data.TroopList.forEach(group => {
                        tempProList.push(_this.getMemberList({groupId: group.GroupId}).then(memberList => {
                            let memberObj = {};
                            memberList.MemberList.forEach(member => {
                                memberObj[member.MemberUin] = member
                            })
                            groupObj[group.GroupId] = {
                                ...group,
                                members: memberObj
                            }
                        }))
                    })
                    Promise.all(tempProList).then(() => {
                        runtimeValue = {
                            ...runtimeValue,
                            groups: groupObj,
                            groupCount: data.TroopList.length
                        }
                        resolve()
                    })
                })
            })
        );
        Promise.all(promiseArr).then(() => {
            fs.writeFile(path.join(__dirname, "../jsonDb/runtimeValues.json"), JSON.stringify(runtimeValue), (err) => {
                if (err) {
                    console.error(err)
                }
            })
        })
    }
}
